package com.lcq.demo.service;

import com.lcq.demo.common.config.AWSConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author 240701005
 */
@Service
@Slf4j
public class FileService {

    @Resource
    private S3Client s3Client;

    @Resource
    private AWSConfig awsConfig;

    /**
     * 获取Bucket下指定目录的所有文件名
     */
    public List<String> listFiles(String prefix) {
        try {
            ListObjectsRequest listObjectsRequest = ListObjectsRequest.builder()
                    .bucket(awsConfig.getBucketName())
                    .prefix(prefix)
                    .build();
            ListObjectsResponse response = s3Client.listObjects(listObjectsRequest);
            List<S3Object> contents = response.contents();
            return contents.stream().map(S3Object::key).collect(Collectors.toList());
        } catch (S3Exception e) {
            log.error(e.awsErrorDetails().errorMessage());
        }
        return null;
    }

    /**
     * 上传文件
     */
    public String uploadFile(MultipartFile file, String fileName, String bucketName) {
        try {
            if (log.isInfoEnabled()) {
                log.info("---------- START UPLOAD FILE :{}----------", fileName);
                log.info("---------- UPLOADING TO BUCKET {} ----------", bucketName);

                String uuid = UUID.randomUUID().toString();
                String newFileName = uuid + "." + getExtension(fileName);
                s3Client.putObject(request -> request.bucket(bucketName).key("product/img/" + newFileName), RequestBody.fromBytes(file.getBytes()));
                log.info("========== UPLOAD FILE DONE ! ==========");
                return s3Client.utilities().getUrl(builder -> builder.bucket(bucketName).key("product/img/" + newFileName)).toString();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    public String getExtension(String originName) {
        String[] res = originName.split("\\.");
        return res[res.length - 1];
    }

    /**
     * 下载文件
     */
    public ResponseInputStream<GetObjectResponse> downloadFile(String fileName, String bucketName) {
        ResponseInputStream<GetObjectResponse> responseInputStream = null;
        try {
            if (log.isInfoEnabled()) {
                log.info("---------- START DOWNLOAD FILE ----------");
                log.info("---------- DOWNLOADING FROM BUCKET {} ----------", bucketName);
                responseInputStream = s3Client.getObject(GetObjectRequest.builder().bucket(bucketName).key(fileName).build());
                log.info("========== DOWNLOAD FILE DONE ! ==========");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return responseInputStream;
    }

    /**
     * 获取文件预签名URL
     */
    public String getFileUrl(String bucketName, String keyName) {
        try (S3Presigner preSigner = S3Presigner.create()) {
            GetObjectRequest getObjectRequest = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(keyName)
                    .build();

            GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofMinutes(5))
                    .getObjectRequest(getObjectRequest)
                    .build();

            PresignedGetObjectRequest presignedGetObjectRequest = preSigner.presignGetObject(getObjectPresignRequest);
            log.info("PreSigned URL: {}", presignedGetObjectRequest.url().toString());
            log.info("HTTP method: {}", presignedGetObjectRequest.httpRequest().method());
            return presignedGetObjectRequest.url().toExternalForm();

        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    private static long calKb(Long val) {
        return val / 1024;
    }

}

